var $ = jQuery;

Dialog = function(pArgs) {
  
  var self = this;
  
  var csDialogId = null;
  
  var coDialog = null;
  
  var coContents = null;
  
  var coLoading = null;
  
  var ciLoading = 0;
    
  var caQueue = [];
  
  var cmDefaultArgs = {
    autoOpen: false,
    resizable: true,
    minHeight: 155,
    modal: false,
    closeOnEscape: false,
    position: ['center', 25],
    buttons: []
  };
  
  var cmCustomArgs = {
    content: null,
    url: null
  };
  
  if(jQuery.browser.msie){
    cmDefaultArgs.resize = function(){ self.getElement().css('width','100%'); self.getElement().parent().css('height','auto');};
    cmDefaultArgs.resizeStop = cmDefaultArgs.resize;
    cmDefaultArgs.drag = function(){ self.getElement().parent().css('height','auto'); };
    cmDefaultArgs.dragStop = cmDefaultArgs.drag;
  }
  
  var _construct = function(pArgs) {
    var mmArgs = cmDefaultArgs;
    var mmCustomArgs = cmCustomArgs;
    
    if (pArgs instanceof jQuery || $.isHTMLElement(pArgs) || typeof (pArgs) == 'string') {
      mmCustomArgs.content = pArgs;
    } else if (typeof (pArgs) == 'object') {
      mmArgs = jQuery.extend({}, cmDefaultArgs, pArgs);
      if (mmArgs.content && mmArgs.url) {
        alert("Arguments 'content' and 'url' cannot be both defined.");
        return;
      }
      for (var a in cmCustomArgs) {
        mmCustomArgs[a] = mmArgs[a];
        delete mmArgs[a];
      }
    }
    coDialog = $('<div id="'+self.getDialogId()+'"/>');
    coDialog.dialog(mmArgs);
    coDialog.data('dialogObject', self);
    coDialog.bind('dialogclose', function() { coDialog.remove(); });
    if (mmCustomArgs.url) {
      self.ajax({
        url: mmCustomArgs.url,
        dataType: 'html',
        success: function(psHtml){
          window.setTimeout(
              function(){
                var msHtml = psHtml.replace(/(<script[^>]*>)/, '$1 var dialog = $("#'+self.getDialogId()+'").data("dialogObject"); ');
                self.setContent(msHtml);
              },
              1
          );
        }
      });
    } else if (mmCustomArgs.content) {
      self.setContent(mmCustomArgs.content);
    }
    self.blurButtons();
  };
  
  /*
   * Este m�todo n�o deve ser sobrescrito em nenhuma subclasse. Sobrescreva o m�todo setInnerContent, se necess�rio.
   */
  self.setContent = function(psHtml){
    self.setInnerContent(psHtml);
    self.enforceMaxHeight();
    coDialog.dialog("option", "position", coDialog.dialog("option", "position"));
  };
  
  self.setInnerContent = function(psHtml){
    coDialog.html(psHtml);
  };
  
  // workaround para o bug: http://bugs.jqueryui.com/ticket/4820
  self.enforceMaxHeight = function() {
    var miMaxHeight = coDialog.dialog('option', 'maxHeight');
    if (miMaxHeight && coDialog.parent().attr('offsetHeight') > miMaxHeight) {
      coDialog.dialog('option', 'height', miMaxHeight);
    }
  };
  
  var getNewId = function(){
    var msDigits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
    var miNum = (new Date()).getTime() % 0x40000000;
    var msId = '';
    do {
      msId = msDigits.charAt(miNum % 64) + msId;
      miNum = Math.floor(miNum / 64);
    } while (miNum > 0);
    return 'dialog' + msId;
  };
  
  self.getDialogId = function(){
    if(!csDialogId){
      csDialogId = getNewId();
    }
    return csDialogId;
  };
  
  self.open = function(pcBeforeOpen){
    if (pcBeforeOpen && typeof pcBeforeOpen == 'function') {
      showLoading();
      coDialog.dialog('open');
      
      //chamada da fun��o de callback
      pcBeforeOpen.call(self);
      
      hideLoading();
    } else {
      coDialog.dialog('open');
    }
  };
  
  var startLoading = function(){
    if(ciLoading == 0){
      showLoading();
    }
    ciLoading++;
  };
  
  var finishLoading = function(){
    ciLoading--;
    if(ciLoading == 0){
      hideLoading();
      unqueue();
    }
  };
  
  self.isLoading = function(){
    return (ciLoading > 0);
  };
  
  self.enqueue = function(pcFunction){
    caQueue.push(pcFunction);
    unqueue();
  };
  
  var unqueue = function(){
    if(!self.isLoading() && caQueue.length > 0){
      caQueue.shift()();
      if(caQueue.length > 0){
        setTimeout(unqueue, 1);
      }
    }
  };
  
	self.ajax = function(pmArgs) {
		var mcSuccess = pmArgs.success;
		var mmArgs = pmArgs;
		
		startLoading();
		mmArgs.success = function(data) {
			mcSuccess(data);
			finishLoading();
		};
		if (mmArgs.data) {
			for (var i in mmArgs.data) {
				if (mmArgs.data[i] === null) {
					delete mmArgs.data[i];
				}
			}
		}
		if (!mmArgs.error) {
			mmArgs.error = function(jqXHR, textStatus, errorThrown) {
				if (jqXHR) {
					finishLoading();
					var element = self.getElement();
					var errorList = $.parseJSON(jqXHR.responseText);
					$.each(errorList, function() {
						var targetElement = $("#" + this.field, element);
						targetElement.attr("title", this.message);
						targetElement.tooltip({
							position: { my: "left top+8", at: "left bottom", collision: "flipfit" },
						    open: function (e) {
						    	setTimeout(function () {
						            $(e.target).tooltip('close');
						        }, 3000);
						    }
						});
						targetElement.tooltip('open');
					});
				}
			};
		}
		mmArgs.global = false;
		mmArgs.type = (mmArgs.type ? mmArgs.type : 'POST');
		$.ajax(mmArgs);
	};
  
  var getLoading = function(){
    if(coLoading == null){
      coLoading = $('<div class="animation">'
                   +  '<div class="loadingBox">'
                   +    '<div><div/>'
                   +    'Carregando...'
                   +  '</div>'
                   +'</div>');
    }
    return coLoading;
  };
  
  var showLoading = function(){
    coContents = coDialog.contents();
    coContents.detach();
    self.disableButtons();
    coDialog.addClass('loading');
    coDialog.prepend(getLoading());
  };
  
  var hideLoading = function(){
    getLoading().remove();
    coDialog.removeClass('loading');
    coContents.appendTo(coDialog);
    self.enableButtons();
  };
  
  self.disableButtons = function() {
    if (arguments.length == 0) {
      //comportamento padrão: desativar todos os botões, exceto o 'cancel' (o último no dom)
      var maButtons = self.getElement().parent().find('.ui-dialog-buttonpane :button:not(:first)');
      
      maButtons.attr('disabled',true);
      maButtons.css('opacity', 0.5);
    } else {
      //ocultar apenas os indicados
      var arg = jQuery.makeArray(arguments);
      coDialog.parent().find('.ui-dialog-buttonpane :button').each(function(i,e) {
        var button = jQuery(e);
        if (jQuery.inArray(button.attr('id'),arg) >= 0)
          button.attr('disabled',true).css('opacity', 0.5);
      });
    }
  };
  
  self.enableButtons = function() {
    if (arguments.length == 0) {
      //comportamento padr�o: ativar todos os bot�es
      coDialog.parent().find('.ui-dialog-buttonpane :button').attr('disabled',false).css('opacity', 1);
    } else {
      //ativar apenas os indicados
      var arg = jQuery.makeArray(arguments);
      coDialog.parent().find('.ui-dialog-buttonpane :button').each(function(i,e) {
        var button = jQuery(e);
        if (jQuery.inArray(button.attr('id'),arg) >= 0)
          button.attr('disabled',false).css('opacity', 1);
      });
    }
  };
  
  self.close = function(dispose){
    coDialog.dialog('close');
  };
  
  self.getElement = function(){
    return coDialog;
  };
  

  self.addButtons = function(pButtons) {
    var mOldButtons = coDialog.dialog("option", "buttons");
    var maAllButtons = [];
    
    if (jQuery.isArray(mOldButtons)) {
      maAllButtons = mOldButtons;
    } else if (mOldButtons) {
      for (var i in mOldButtons) {
        maAllButtons.push(mOldButtons[i]);
      }
    }
    if (jQuery.isArray(pButtons)) {
      maAllButtons = maAllButtons.concat(pButtons.reverse());
    } else {
      maAllButtons.push(pButtons);
    }
    coDialog.dialog("option", "buttons", maAllButtons);
    if (self.isLoading()) {
      self.disableButtons();
    }
    self.blurButtons();
  };
  
  self.blurButtons = function(){
    self.enqueue(function(){
      var moButtons = self.getElement().parent().find(':button');
      moButtons.click(function(){$(this).blur();});
      setTimeout(function(){moButtons.blur();},1);
    });
  };

	self.changeButtonLabel = function(id, newLabel) {
		coDialog.parent().find('.ui-dialog-buttonpane :button').each(function(i,e) {
			var button = jQuery(e);
			var bid = button.attr('id');
			if (bid == id) {
				button.button("option", "label", newLabel);
			}
		});
	};
  
  self.setTitle = function(psTitle){
    coDialog.dialog("option", "title", psTitle);
  };
  
  self.find = function(psSelector) {
    return self.getElement().find(psSelector);
  };
  
  self.getValue = function(psFieldName) {
    var moField = self.find('[name="'+psFieldName+'"]');
    if (moField.is('[type=radio]')) {
      return moField.filter(':checked').val();
    } else {
      return moField.val();
    }
  };
  
  _construct(pArgs);
  return self;
};

/**
 * 
 */
ModalDialog = function(__height__, __width__, __resizable__, __selector__, __openButtonSelector__) {

	/**
	 *
	 */
	var _this = this;
	
	/**
	 *
	 */
	var _initialState = "";

	/**
	 *
	 */
	var _height = 200;
	
	/**
	 *
	 */
	var _width = 300;
	
	/**
	 *
	 */
	var _resizable = false;
	
	/**
	 *
	 */
	var _modal = true;
	
	/**
	
	/**
	 *
	 */
	var _dialogButtons = new Array();

	/**
	 *
	 */
	var _closeFunction = null;
	
	/**
	 *
	 */
	var _closeButtonId = null;

	/**
	 *
	 */
	var _selector = null;

	/**
	 *
	 */
	var _openButtonSelector = null;
	
	/**
	 *
	 */
	var _openFunction = null;

	/**
	 *
	 */
	var _parameter = null;
	
	/**
	 *
	 */
	var _open = false;
	
	/**
	 * 
	 */
	var _isConfigured = false;
	
	/**
	 *
	 */
	var _init = function(_selector_, _openButtonSelector_, _height_, _width_, _resizable_) {
		_this.setSelector(_selector_);
		_this.setInitialState(jQuery(_selector_).html());
		_this.setOpenButtonSelector(_openButtonSelector_);
		_this.setHeight(_height_);
		_this.setWidth(_width_);
		_this.setResizable(_resizable_);
		
		if (_this.getOpenButtonSelector()) {
			applyButtonTheme(_this.getOpenButtonSelector());
			
			jQuery(_this.getOpenButtonSelector()).click(function() {
				_this.show();
				jQuery(_this.getOpenButtonSelector()).removeClass('ui-state-hover ui-state-focus');
			});
		}
	};

	/**
	 *
	 */
	var _configDialog = function() {
		_this.setContent(_this.getInitialState());
		_this.enableButtons();
		
		var confirmDialogOpts = {
			bgiframe: true,
			autoOpen: false,
			height: _this.getHeight(),
			width: _this.getWidth(),
			minWidth: 300,
			resizable: _this.getResizable(),
			modal: _this.getModal(),
			closeOnEscape: false,
			open: function() {				
				_setOpen(true);
			},
			
			close: function() {
				_setOpen(false);
			}
		};
		
		if (!_isConfigured) {
			_isConfigured = true;

			if (_this.getOpenFunction()) {
				jQuery(_this.getSelector()).bind('dialogopen', function(event, ui) {
					_this.getOpenFunction().call(null);
				});
			}
			
			_this.addCloseButton(
					isEmpty(_this._getDialogButtons()) ? "Fechar" : "Cancelar",
					function () {
						if (_this.getCloseFunction()) {
							_this.getCloseFunction().call(null);
						} else {
							_this.close();
						}
					}
			);
		}
		
		confirmDialogOpts.buttons = _this._getDialogButtons();
		
		jQuery(_this.getSelector()).dialog(confirmDialogOpts);
	};

	/**
	 *
	 */
	this._getDialogButtons = function() {
		return _dialogButtons;
	};

	/**
	 *
	 */
	this.show = function() {
		if (!_this.isOpen()) {
			_configDialog();
			
			jQuery(_this.getSelector()).dialog('open');
		} else {
			if (_this.getOpenFunction()) {
				_this.getOpenFunction().call(null);
			}
		}
	};

	/**
	 *
	 */
	this.close = function() {
		jQuery(_this.getSelector()).dialog('close');
	};

	/**
	 *
	 */
	this.addDialogButton = function(_buttonId_, _buttonFunction_, _buttonLabel_) {
		var insertionIndex = _dialogButtons.length;
		for (var i = 0; i < _dialogButtons.length; i++) {
			if (_dialogButtons[i].id == _buttonId_) {
				insertionIndex = i;
				break;
			}
		}
		
		var _formButtonFunction = function(event) {
			event.preventDefault();
			_buttonFunction_.call(null);
		};
		
		_dialogButtons[insertionIndex] = {
					id: _buttonId_,
					text: (_buttonLabel_ ? _buttonLabel_ : _buttonId_),
					click: _formButtonFunction
				};
	};
	
	/**
	 * 
	 */
	this.renameDialogButton = function(buttonId, newLabel) {
		var dialogJquery = jQuery(_this.getSelector());
		var buttons = dialogJquery.dialog( "option", "buttons" );
		for (var i in buttons) {
			var button = buttons[i];
			if (button.id == buttonId) {
				button.text = newLabel;
				dialogJquery.dialog( "option", "buttons", buttons );
				return true;
			}
		}
		return false;
	};
	
	/**
	 * 
	 */
	this.renameCloseButton = function(newLabel) {
		_this.renameDialogButton(_closeButtonId,newLabel);
	};

	/**
	 *
	 */
	this.addCloseButton = function(_buttonLabel_, _buttonFunction_) {
		if(! _closeButtonId) {
			_dialogButtons[_dialogButtons.length] = {
						id: _buttonLabel_,
						text: _buttonLabel_,
						click: function(event) {
							event.preventDefault();
							_buttonFunction_.call(null);
						} 
					};
			_closeButtonId = _buttonLabel_;
		}
	};
	
	/**
	 *
	 */
	this.disableButtons = function(_id_) {
		var buttons = jQuery('.ui-dialog-buttonpane button');
		  for ( var i = 0; i < buttons.length; i++ ) {
			  var b = jQuery(buttons[i]);
			  var buttonId = b.attr('id');
			  if (_id_ === undefined || buttonId == _id_
					  || (jQuery.isArray(_id_) && jQuery.inArray(buttonId,_id_) >= 0)) {
				  b.attr('disabled', true); 
				  b.css('opacity', 0.5);
			  }
		  }
	};

	/**
	 *
	 */
	this.enableButtons = function(_id_) {
		var buttons = jQuery('.ui-dialog-buttonpane button');
		  for ( var i = 0; i < buttons.length; i++ ) {
			  var b = jQuery(buttons[i]);
			  var buttonId = b.attr('id');
			  if (_id_ === undefined || buttonId == _id_
					  || (jQuery.isArray(_id_) && jQuery.inArray(buttonId,_id_) >= 0)) {
				  b.attr('disabled', false);
				  b.removeClass('ui-state-hover ui-state-focus');
				  b.css('opacity', 1);
			  }
		  }
	};
	
	/**
	 * 
	 */
	this.enableCloseButton = function() {
		_this.enableButtons(_closeButtonId);
	};
	
	/**
	 * 
	 */
	this.setSize = function(_width_, _height_) {
		jQuery(_this.getSelector())
			.dialog( "option", "width", _width_ )
			.dialog( "option", "height", _height_ )
			.dialog( "option", "position", "center" );
	};

	/**
	 *
	 */
	this.getValue = function(field) {
		var inputField = jQuery(_this.getSelector() + " [name=" + field + "]");
		if (inputField.is('[type=radio]')) {
			return inputField.filter(':checked').val();
		} else {
			return inputField.val();
		}
	};
	
	/**
	 *
	 */
	this.setContent = function(strHTML) {
		jQuery(_this.getSelector()).html(strHTML);
	};
	
	/**
	 *
	 */
	this.setTitle = function(title) {
		jQuery(_this.getSelector()).dialog( "option", "title", title );
	};
	
	/**
	 *
	 */
	this.setCloseFunction = function(_closeFunction_) {
		_closeFunction = _closeFunction_;
	};

	/**
	 *
	 */
	this.getCloseFunction = function() {
		return _closeFunction;
	};
	
	/**
	 *
	 */
	this.setSelector = function(_selector_) {
		_selector = _selector_;
	};

	/**
	 *
	 */
	this.getSelector = function() {
		return _selector;
	};

	/**
	 *
	 */
	this.setHeight = function(_height_) {
		_height = _height_;
	};

	/**
	 *
	 */
	this.getHeight = function() {
		return _height;
	};
	
	/**
	 *
	 */
	this.setWidth = function(_width_) {
		_width = _width_;
	};

	/**
	 *
	 */
	this.getWidth = function() {
		return _width;
	};

	/**
	 *
	 */
	this.setResizable = function(_resizable_) {
		_resizable = _resizable_;
	};

	/**
	 *
	 */
	this.getResizable = function() {
		return _resizable;
	};
	
	/**
	 *
	 */
	this.setModal = function(_modal_) {
		_modal = _modal_;
	};

	/**
	 *
	 */
	this.getModal = function() {
		return _modal;
	};
	
	/**
	 *
	 */
	this.setParameter = function(_parameter_) {
		_parameter = _parameter_;
	};

	/**
	 *
	 */
	this.getParameter = function() {
		return _parameter;
	};
	
	/**
	 *
	 */
	this.setOpenButtonSelector = function(_openButtonSelector_) {
		_openButtonSelector = _openButtonSelector_;
	};

	/**
	 *
	 */
	this.getOpenButtonSelector = function() {
		return _openButtonSelector;
	};
	
	/**
	 * 
	 */
	this.getOpenFunction = function() {
		return _openFunction;
	};

	/**
	 * 
	 */
	this.setOpenFunction = function(_openFunction_) {
		_openFunction = _openFunction_;
	};
	
	/**
	 *
	 */
	this.setInitialState = function(_initialState_) {
		_initialState = _initialState_;
	};

	/**
	 *
	 */
	this.getInitialState = function() {
		return _initialState;
	};
	
	/**
	 *
	 */
	var _setOpen = function(_open_) {
		_open = _open_;
	};

	/**
	 *
	 */
	this.isOpen = function() {
		return _open;
	};
	
	_init(__selector__, __openButtonSelector__, __height__, __width__, __resizable__);

};

function applyButtonTheme(_buttonSelector_) {
	jQuery(_buttonSelector_).button().removeClass("ui-button-text-only");
};

/******************
 * Confirm dialog *
 ******************/

ConfirmDialog = function(pmArgs){
	  
  var self = null;
  
  var cmDefaultArgs = {
    title: 'Confirmação',
    content: null,
    confirmText: 'Confirmar',
    cancelText: 'Cancelar',
    confirmCallback: null,
    cancelCallback: null,
    modal: true
  };
  
  var _construct = function(pmArgs){
    var mmArgs = jQuery.extend({}, cmDefaultArgs, pmArgs);
    self = new Dialog(mmArgs);
    self.getElement().parent().children().children('.ui-dialog-titlebar-close').hide();
    self.addButtons([
      {
        text: mmArgs.confirmText,
        click: function(){
          self.close();
          if(mmArgs.confirmCallback && typeof(mmArgs.confirmCallback) == 'function'){
            mmArgs.confirmCallback();
          }
        }
      },
      {
        text: mmArgs.cancelText,
        click: function(){
          self.close();
          if(mmArgs.cancelCallback && typeof(mmArgs.cancelCallback) == 'function'){
            mmArgs.cancelCallback();
          }
        }
      }
    ]);
  };
  
  _construct(pmArgs);
  return self;
};

ConfirmDialog.confirm = function(pmArgs){
  (new ConfirmDialog(pmArgs)).open();
};

/******************
 *   Form  dialog *
 ******************/

FormDialog = function(pArgs){
	  
	  var self = new Dialog(pArgs);
	  
	  var cmDefaultArgs = {
	    title: '',
	    content: '',
	    closeText: 'Fechar',
	    closeCallback: null,
	    modal: true
	  };
	  
	  var _construct = function(pArgs){
	    var mmArgs = cmDefaultArgs;
	    
	    if(pArgs instanceof jQuery || $.isHTMLElement(pArgs) || typeof(pArgs) == 'string'){
	      mmArgs.content = pArgs;
	    }else if(typeof(pArgs) == 'object'){
	      mmArgs = jQuery.extend({}, mmArgs, pArgs);
	    }

	    self.getElement().dialog('option', 'modal', mmArgs.modal);
	    self.setTitle(mmArgs.title);
	    // adiciona o botao de fechar
	    self.addButtons([
	      {
	        id: 'defaultClose',
	        text: mmArgs.closeText,
	        click: function(){
	          self.close();
	          if(mmArgs.closeCallback && typeof(mmArgs.closeCallback) == 'function'){
	            mmArgs.closeCallback();
	          }
	        }
	      }
	    ]);
	  };
	  
	  _construct(pArgs);
	  return self;
	};

/******************
 *   Info  dialog *
 ******************/
InfoDialog = function(pArgs){
	  
	  var self = null;
	  
	  var cmDefaultArgs = {
	    title: 'Informação',
	    content: null,
	    closeText: null,
	    closeCallback: null,
	    modal: true
	  };
	  
	  var _construct = function(pArgs){
	    var mmArgs = cmDefaultArgs;
	    
	    if(pArgs instanceof jQuery || $.isHTMLElement(pArgs) || typeof(pArgs) == 'string'){
	      mmArgs.content = pArgs;
	    }else if(typeof(pArgs) == 'object'){
	      mmArgs = jQuery.extend({}, mmArgs, pArgs);
	    }
	    self = new Dialog(mmArgs);
	    if(mmArgs.closeText != null) {
	      self.addButtons([
	        {
	          text: mmArgs.closeText,
	          click: function(){
	            self.close();
	            if(mmArgs.closeCallback && typeof(mmArgs.closeCallback) == 'function'){
	              mmArgs.closeCallback();
	            }
	          }
	        }
	      ]);
	    }
	  };
	  
	  _construct(pArgs);
	  return self;
	};

	InfoDialog.show = function(pArgs){
	  (new InfoDialog(pArgs)).open();
	};

/******************
 *  Yes/No dialog *
 ******************/
YesNoDialog = function(pmArgs){
	  
	  var cmDefaultArgs = {
	    confirmText: 'Sim',
	    cancelText: 'Não'
	  };
	  
	  var self = new ConfirmDialog(jQuery.extend({}, pmArgs, cmDefaultArgs));
	  
	  return self;
	};

	YesNoDialog.confirm = function(pmArgs){
	  (new YesNoDialog(pmArgs)).open();
	};